home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1995 August: Tool Chest / Dev.CD Aug 95 TC / Dev.CD Aug 95 TC.toast / New System Software Extensions / QuickDraw™ 3D 1.0 / Samples / SampleCode / Skinny3DSample / Skinny3DSources ƒ / 3DAppSpecific.c next >
Encoding:
C/C++ Source or Header  |  1995-04-15  |  26.0 KB  |  1,029 lines  |  [TEXT/MPS ]

  1. #include "Printing.h"
  2. #include "Windows.h"
  3. #include "Fonts.h"
  4. #include "Desk.h"
  5. #include "ToolUtils.h"
  6. #include "TextUtils.h"
  7. #include "LowMem.h"
  8. #include "SegLoad.h"
  9.  
  10.  
  11. #include    "3DAppSpecific.h"
  12.     // #include <QD3DHeaders.h>
  13. #include     "SkinnyMain.h"
  14. #include     "ValueControls.h"
  15.  
  16. #include     "BoxModel.h"
  17. #include    "Cameras.h"
  18. #include     "Lights.h"
  19.  
  20. /*
  21. prototypes of QD3DFunctions called from the application (in "3DAppSpecific.h"):
  22.  
  23. OSErr    InitializeApplication(void);
  24. void    Cleanup(void);
  25. Boolean PreflightNew(void); // return TRUE if "New" will work
  26. void     DoNew(void);
  27. void     DoOpen(void);
  28. void     DoClose(void); // FrontWindow() only
  29. void     DoSave(void);
  30. void     DoSaveAs(void);
  31. void     DoPrint(void);
  32. void     DoClickInContent(EventRecord *evt, WindowPtr theWindow);
  33. void     ActivateWindow(WindowPtr newFrontWindow, Boolean active);
  34.  
  35. void    DoAppSpecificMenu(long menuNumber, long itemNumber);
  36. void     UpdateAppMenus(void);
  37.  
  38. void    DrawAppSpecificContent(WindowPtr theWindow);
  39.  
  40. */
  41. enum { windowID = 128 }; // resource ID
  42.  
  43. #define kWidth        600
  44. #define kHeight        400
  45. #define kCntrlWdth    200
  46.  
  47. typedef enum DirectionType {
  48.     none, left, right, up, down, reset
  49. } DirectionType;
  50.  
  51. // data structure tied to a window (handle into wRefCon)
  52. struct WindowInfo {
  53.     TQ3ViewObject        view;
  54.     TQ3GroupObject        model;
  55.     TQ3TransformObject    rotation;
  56.     TQ3StyleObject        interpolation;
  57.     TQ3StyleObject        backfacing;
  58.     TQ3StyleObject        fillstyle;
  59.     TQ3ShaderObject         shader;
  60.     VccPtr                vcc;
  61. };
  62. typedef struct WindowInfo WindowInfo, **WinfoH;
  63.  
  64.  
  65. // local prototypes
  66. void AddHierarchMenu(long parentMenuID, long item, long subMenuID);
  67.  
  68. static    WinfoH     Make3Dinfo(WindowPtr theWindow);
  69. static    void    Dispose3Dinfo(WinfoH wInfoH);
  70.  
  71. static    void    Draw3DPart(WinfoH wInfo);
  72. static     void    DrawDirections(void);
  73. static     void    DrawTriangle(Point p, DirectionType e);
  74. static    void    DrawControlPart(WinfoH wInfo);
  75. static    Boolean            ControlClick(Point pt, WindowPtr theWindow);
  76. static    DirectionType     RotationClick(Point pt, WindowPtr theWindow);
  77.  
  78. static    TQ3DrawContextObject    MakeDrawContext(WindowPtr theWindow);
  79.  
  80. static void SetRotation(WinfoH wInfo, DirectionType direction);
  81.  
  82. static     void     ChooseDebug(long item);
  83.  
  84. static    void    ChooseRenderer    (TQ3ViewObject view, long item);
  85.  
  86. static    void    ChooseBackfacing    (WinfoH wInfo, long item);
  87. static    void    ChooseInterpolation    (WinfoH wInfo, long item);
  88. static    void    ChooseFillStyle        (WinfoH wInfo, long item);
  89.  
  90. static    void    MakeGeometry        (WinfoH wInfo, long selector);
  91. static    void    UpdateGeometry        (WinfoH wInfo);
  92. static    void    MakeDataControl        (WinfoH wInfo);
  93. static    void    MakeNewCamera        (WinfoH wInfo, long selector);
  94. static    void    MakeCameraControl    (WinfoH wInfo);
  95. static    void    MakeLightControl    (WinfoH wInfo, long selector);
  96.  
  97. static     Boolean GoodFrontWindow(WindowPtr *theWindow, WinfoH *wInfo);
  98. void     CheckMenuItem(short menuID, short checkItem);
  99.  
  100. static     Rect    gWindowRect;
  101. static     Rect    g3DViewRect;
  102. Rect    gContrlRect; // needed to make VCC
  103.  
  104. static long curGeometry;
  105. static long curCamera;
  106. static long curLight;
  107. static long curRenderer;
  108. static long curBackfacing;
  109. static long curInterpol;
  110. static long curFillStyle;
  111.  
  112.  
  113. extern    THPrint        gPrintH;
  114. extern     CursHandle    gWatchCursor;
  115.  
  116.  
  117. //---------------------------------
  118. OSErr    InitializeApplication(void)
  119. {
  120.     MenuHandle    mh;
  121.     Handle         menuBar = GetNewMBar(128);
  122.     TQ3Status    status;
  123.     
  124.     if (!menuBar) {
  125.         return -30000;       
  126.     }
  127.     SetMenuBar(menuBar);
  128.     AddResMenu(GetMHandle(mApple),'DRVR');
  129.     DrawMenuBar();
  130.     DisposHandle(menuBar);
  131.     
  132.     AddHierarchMenu(mControl, iCamera,         mCameras);
  133.     AddHierarchMenu(mControl, iLight,         mLight);
  134.     AddHierarchMenu(mControl, iRenderer,     mRenderer);
  135.     
  136.     AddHierarchMenu(mStyle,   iBackfacing,    mBackfacing);
  137.     AddHierarchMenu(mStyle,   iInterpol,     mInterpolation);
  138.     AddHierarchMenu(mStyle,   iFillStyle,    mFillStyle);
  139.     
  140.     gPrintH = (THPrint)NewHandle(sizeof(TPrint));
  141.     if (gPrintH == nil)
  142.         return -30001;       
  143.     
  144.     status = Q3Initialize();
  145.     if ( status == kQ3Failure )
  146.         return ( -30002 );
  147.  
  148.     SetRect(&gWindowRect, 0, 0, kWidth, kHeight);
  149.     SetRect(&g3DViewRect, 0, 0, kWidth - kCntrlWdth, kHeight);
  150.     SetRect(&gContrlRect, kWidth - kCntrlWdth, 0, kWidth, kHeight);
  151.     InsetRect(&gContrlRect, 1, 1);
  152.  
  153.     return ( noErr );
  154. }
  155.  
  156. //---------------------------------------------------------------
  157. void AddHierarchMenu(long parentMenuID, long item, long subMenuID)
  158. {
  159.     MenuHandle    mh;
  160.     
  161.     mh = GetMenu(subMenuID);
  162.     InsertMenu(mh, -1);
  163.     mh = GetMHandle(parentMenuID);
  164.     SetItemCmd(mh, item, 0x1B);
  165.     SetItemMark(mh, item, (char)subMenuID);
  166. }
  167.  
  168.  
  169. //------------------------
  170. void    Cleanup(void)
  171. //------------------------
  172. {
  173.     TQ3Status status = Q3Exit();
  174.     // don't worry - the application heap disappears anyway,
  175.     // and we can't do anything about any failure of Q3Exit().
  176. }
  177.  
  178. //------------------------------------
  179. Boolean PreflightNew(void)
  180. {
  181.     long maxm, grow;
  182.     
  183.     maxm = MaxMem(&grow);
  184.     return (maxm > 1000000); // that's what our new QD3D window roughly needs!
  185. }
  186.  
  187. //------------------------------------
  188. void DoNew(void)
  189. {
  190.     WindowPtr    myWindow;
  191.     WinfoH        intoRefCon;
  192.     
  193.     myWindow = GetNewCWindow(windowID, nil, (WindowPtr)(-1));
  194.     if ( myWindow == nil ) {
  195.         ErrMsg("\pGetNewCWindow failed.");
  196.         return;
  197.     }
  198.     SizeWindow(myWindow, kWidth, kHeight, false);
  199.     ShowWindow(myWindow);
  200.     SetPort(myWindow);
  201.     intoRefCon = Make3Dinfo(myWindow);
  202.     if (intoRefCon != nil) {
  203.         SetWRefCon(myWindow, (long)intoRefCon );
  204.         DoAppSpecificMenu(mGeometry, iBox);
  205.     }
  206.     else {
  207.         ErrMsg("\pMake3Dinfo failed");
  208.         DisposeWindow(myWindow);
  209.     }
  210. }
  211.  
  212.  
  213. //------------------------------------
  214. void DoOpen(void)
  215. {
  216. }
  217.  
  218. //------------------------------------
  219. void DoClose(void)
  220. {
  221.     WindowPtr    theWindow;
  222.     WinfoH        theWinfo;
  223.     
  224.     if (GoodFrontWindow(&theWindow, &theWinfo))
  225.         Dispose3Dinfo(theWinfo);
  226.     CloseWindow(theWindow);
  227. }
  228.  
  229. //------------------------------------
  230. void DoSave(void)
  231. {
  232. }
  233.  
  234. //------------------------------------
  235. void DoSaveAs(void)
  236. {
  237. }
  238.  
  239. //------------------------------------
  240. void DoPrint( void )
  241. {
  242.     SysBeep(50);
  243. }
  244.  
  245. //----------------------------------------------------------------------
  246. void DoClickInContent(EventRecord *evt, WindowPtr theWindow)
  247. {
  248.     WinfoH            wInfo;
  249.     ControlHandle    ctlh;
  250.     Point            pt;
  251.     Rect            frame;
  252.     DirectionType    direction;
  253.     int                part;
  254.     
  255.     wInfo = (WinfoH)GetWRefCon(theWindow);
  256.     if (wInfo == nil) return;
  257.  
  258.     pt = evt->where;
  259.     GlobalToLocal(&pt);
  260.     if (part = FindControl(pt, theWindow, &ctlh)) {
  261.         /* TrackControl Goes Here */
  262.     }
  263.  
  264.     if (ControlClick(pt, theWindow)) { // our special ValueControl panel
  265.         InvalRect(&g3DViewRect);
  266.         return;
  267.     }
  268.     
  269.     if ((direction = RotationClick(pt, theWindow)) != none) {
  270.         SetRotation(wInfo, direction);
  271.         InvalRect(&g3DViewRect);
  272.     }
  273. }
  274.  
  275.  
  276. //------------------------------------
  277. static void SetRotation(WinfoH wInfo, DirectionType direction)
  278. {
  279.     TQ3Status            status;
  280.     TQ3BoundingBox        bBox;
  281.     TQ3Point3D            center, tmpPt;
  282.     TQ3Axis                axis;
  283.     float                angle;
  284.     TQ3Matrix4x4            previousMatrix, matrix, newMatrix, *tmp;
  285.     TQ3TransformObject     transform;
  286.     TQ3RotateAboutPointTransformData    tData;
  287.  
  288.     TQ3GroupObject        group;
  289.     TQ3GroupPosition        position;
  290.     TQ3ObjectType        type;
  291.     TQ3Object            theObj;
  292.     TQ3BoxData            boxData;
  293.     
  294.     if (direction == reset) {
  295.         Q3Matrix4x4_SetIdentity(&matrix);
  296.         status = Q3MatrixTransform_Set((**wInfo).rotation, &matrix);
  297.         return;
  298.     }
  299.     
  300. //    Q3View_StartBounds((**wInfo).view);
  301. //    status = Q3DisplayGroup_BoundingBox((**wInfo).model, 
  302. //                                        &bBox, 
  303. //                                         kQ3ComputeBoundsApproximate,
  304. //                                         (**wInfo).view);
  305. //    Q3View_EndBounds((**wInfo).view);
  306.     
  307.     // Cannot link with the above, for some temporary reason.
  308.     // Temporary workaround:
  309.     group = (**wInfo).model;
  310.     type = kQ3ShapeTypeGeometry;
  311.     status = Q3Group_GetFirstPositionOfType(group, type, &position);
  312.     if (status == kQ3Failure)
  313.         return;
  314.         
  315.     status = Q3Group_GetPositionObject ( group, position, &theObj);
  316.     type = Q3Geometry_GetType ( theObj );
  317.     switch (type) {
  318.         case kQ3GeometryTypeBox: 
  319.                 status = Q3Box_GetData( theObj, &boxData );
  320.                 bBox.min = boxData.origin;
  321.                 Q3Point3D_Vector3D_Add(&bBox.min, &boxData.orientation, &tmpPt);
  322.                 Q3Point3D_Vector3D_Add(&tmpPt,    &boxData.majorAxis, &tmpPt);
  323.                 Q3Point3D_Vector3D_Add(&tmpPt,       &boxData.minorAxis, &bBox.max);
  324.             break;
  325.             // add here the cases of other geometries, if required
  326.         default:
  327.             Q3Point3D_Set(&bBox.min, -1.0, -1.0, -1.0);
  328.             Q3Point3D_Set(&bBox.max, 1.0, 1.0, 1.0);
  329.             return;
  330.     }
  331.  
  332.     Q3Point3D_RRatio(&bBox.min, &bBox.max, 1.0, 1.0, ¢er); // mid-point
  333.     
  334.     status = Q3MatrixTransform_Get((**wInfo).rotation, &previousMatrix);
  335.     
  336.     if ((direction == up) || (direction == down))
  337.         axis = kQ3AxisX;
  338.     else
  339.         axis = kQ3AxisY;
  340.     if ((direction == right) || (direction == down))
  341.         angle = 0.1;
  342.     else
  343.         angle = -0.1;
  344.         
  345.     tData.axis = axis;
  346.     tData.radians = angle;
  347.     tData.about = center;
  348.     transform = Q3RotateAboutPointTransform_New(&tData);
  349.     if (transform == NULL)
  350.         return;
  351.     tmp = Q3Transform_GetMatrix(transform, &matrix);
  352.     
  353.     Q3Matrix4x4_Multiply(&previousMatrix, &matrix, &newMatrix);
  354.     status = Q3MatrixTransform_Set((**wInfo).rotation, &newMatrix);
  355.  
  356.  
  357. //------------------------------------
  358. void     ActivateWindow(WindowPtr newFrontWindow, Boolean active)
  359. {
  360.     if (active)
  361.         ;// This window is now active.  Controls should be enabled, etc.
  362.     else
  363.         ;
  364.     //    do anyting necessary to deactivate your windows here.
  365.     //    controls should be dimmed, etc.
  366. }
  367.  
  368. //------------------------------------
  369. void    DoAppSpecificMenu(long menuNumber, long item)
  370. {
  371.     WindowPtr    theWindow;
  372.     WinfoH        wInfo;
  373.     
  374.     if (menuNumber == mDebug) {
  375.         ChooseDebug(item); return;
  376.     }
  377.     
  378.     if (!GoodFrontWindow(&theWindow, &wInfo)) {
  379. //        ErrMsg("\pBad FrontWindow");
  380.         return;
  381.     }
  382.     
  383.     switch (menuNumber) {
  384.         case mGeometry: MakeGeometry(wInfo, item);
  385.                         MakeDataControl(wInfo);
  386.                         curGeometry = item;
  387.                         break;
  388.         case mControl:     if (item == iData)
  389.                         MakeDataControl(wInfo);
  390.                         break;
  391.                 
  392.         case mCameras:     if (item != curCamera) {
  393.                             MakeNewCamera(wInfo, item);
  394.                             curCamera = item;
  395.                         }
  396.                         MakeCameraControl(wInfo);
  397.                         break;
  398.         case mLight:     MakeLightControl(wInfo, item);
  399.                         curLight = item;
  400.                         break;
  401.         case mRenderer: ChooseRenderer((**wInfo).view, item);
  402.                         break;
  403.  
  404.         case mBackfacing:
  405.                         ChooseBackfacing(wInfo, item);
  406.                         curBackfacing = item;
  407.                         break;
  408.         case mInterpolation:
  409.                         ChooseInterpolation(wInfo, item);
  410.                         curInterpol = item;
  411.                         break;
  412.         case mFillStyle:
  413.                         ChooseFillStyle(wInfo, item);
  414.                         curFillStyle = item;
  415.                         break;
  416.         
  417.         default:
  418.             break;
  419.     }
  420.     InvalRect(&theWindow->portRect);
  421. }
  422.  
  423.  
  424. //------------------------------------
  425. void UpdateAppMenus(void)
  426. {
  427.     long free, maxm, grow;
  428.     Str255 freeItem = "\pFreeMem = ";
  429.     Str255 maxmItem = "\pMaxMem  = ";
  430.     Str255 s;
  431.     WindowPtr    theWindow;
  432.     WinfoH        wInfo;
  433.     MenuHandle    menu = GetMHandle(mDebug);
  434.     
  435.     free = FreeMem();
  436.     NumToString(free, s);
  437.     pcat(freeItem, s);
  438.     SetItem(menu, iFreeMem, freeItem);
  439.  
  440.     maxm = MaxMem(&grow);
  441.     NumToString(maxm, s);
  442.     pcat(maxmItem, s);
  443.     SetItem(menu, iMaxMem, maxmItem);
  444.     
  445.     CheckMenuItem(mGeometry, curGeometry);
  446.     CheckMenuItem(mCameras, curCamera);
  447.     CheckMenuItem(mLight, curLight);
  448.     CheckMenuItem(mRenderer, curRenderer);
  449.     CheckMenuItem(mBackfacing, curBackfacing);
  450.     CheckMenuItem(mInterpolation, curInterpol);
  451.     CheckMenuItem(mFillStyle, curFillStyle);
  452.     
  453.     if (!GoodFrontWindow(&theWindow, &wInfo)) {
  454.         DisableItem(GetMHandle(mGeometry), 0);
  455.         DisableItem(GetMHandle(mControl), 0);
  456.         DisableItem(GetMHandle(mStyle), 0);
  457.     }
  458.     else {
  459.         EnableItem(GetMHandle(mGeometry), 0);
  460.         EnableItem(GetMHandle(mControl), 0);
  461.         EnableItem(GetMHandle(mStyle), 0);
  462.     }
  463.     DrawMenuBar();
  464. }
  465.  
  466.  
  467. void CheckMenuItem(short menuID, short checkItem)
  468. {
  469.     MenuHandle    menu = GetMHandle(menuID);
  470.     short         n = CountMItems(menu);
  471.     short        i;
  472.     
  473.     for (i = 1; i <= n; i++)
  474.         CheckItem(menu, i, (i == checkItem));
  475. }
  476.  
  477.  
  478. //------------------------------------
  479. static    void    ChooseRenderer(TQ3ViewObject view, long item)
  480. {
  481.     TQ3Status            status;
  482.     TQ3ObjectType        rType;
  483.     TQ3RendererObject    renderer;
  484.     
  485.     switch (item) {
  486.         case iWireFrame: rType = kQ3RendererTypeWireFrame;     break;
  487.         case iZBuffer:     rType = kQ3RendererTypeInteractive;     break;
  488.     }
  489.     
  490. //    status = Q3View_SetRendererByType(view, rType);
  491. //  alternatively:
  492.     renderer = Q3Renderer_NewFromType(rType);
  493.     if (renderer == nil)
  494.         return;
  495.     status = Q3View_SetRenderer(view, renderer);
  496.     if (status == kQ3Failure )
  497.         return;
  498.         
  499.     Q3Object_Dispose(renderer) ;
  500.  
  501.     curRenderer = item;
  502. }
  503.  
  504. //------------------------------------
  505. static    void    ChooseBackfacing(WinfoH    wInfo, long item)
  506. {
  507.     TQ3Status            status;
  508.     TQ3BackfacingStyle     bfStyle;
  509.     
  510.     switch (item) {
  511.         case iBoth:     bfStyle = kQ3BackfacingStyleBoth;             break;
  512.         case iRemove:    bfStyle = kQ3BackfacingStyleRemove;     break;
  513.           case iFlip:     bfStyle = kQ3BackfacingStyleFlip;         break;
  514.     }
  515.     if ((**wInfo).backfacing != nil)
  516.         status = Q3Object_Dispose((**wInfo).backfacing);
  517.     (**wInfo).backfacing = Q3BackfacingStyle_New(bfStyle);
  518. }
  519.  
  520. //------------------------------------
  521. static    void    ChooseInterpolation(WinfoH    wInfo, long item)
  522. {
  523.     TQ3Status                status;
  524.     TQ3InterpolationStyle    ipStyle;
  525.     
  526.     switch (item) {
  527.         case iNone:     ipStyle = kQ3InterpolationStyleNone;     break;
  528.         case iVertex:    ipStyle = kQ3InterpolationStyleVertex;     break;
  529.           case iPixel:     ipStyle = kQ3InterpolationStylePixel;     break;
  530.     }
  531.     if ((**wInfo).interpolation != nil)
  532.         status = Q3Object_Dispose((**wInfo).interpolation);
  533.     (**wInfo).interpolation = Q3InterpolationStyle_New(ipStyle);
  534. }
  535.  
  536.  
  537. //------------------------------------
  538. static    void    ChooseFillStyle(WinfoH    wInfo, long item)
  539. {
  540.     TQ3Status            status;
  541.     TQ3FillStyle            flStyle;
  542.     
  543.     switch (item) {
  544.         case iFilled:     flStyle = kQ3FillStyleFilled;    break;
  545.         case iEdges:    flStyle = kQ3FillStyleEdges;    break;
  546.           case iPoints:     flStyle = kQ3FillStylePoints;    break;
  547.     }
  548.     if ((**wInfo).fillstyle != nil)
  549.         status = Q3Object_Dispose((**wInfo).fillstyle);
  550.     (**wInfo).fillstyle = Q3FillStyle_New(flStyle);
  551. }
  552.  
  553.  
  554. //------------------------------------
  555. static void ChooseDebug(long item)
  556. {    
  557. }
  558.  
  559. //////////////////////////////////////////////////////////
  560. //===========================================
  561. WinfoH Make3Dinfo(WindowPtr theWindow)
  562. {
  563.     WinfoH                wInfo;
  564.     TQ3DrawContextObject drawContext;
  565.     TQ3RendererObject    renderer;
  566.     TQ3GroupObject        lightGroup;
  567.     TQ3Matrix4x4            matrix;
  568.     TQ3Status            status;
  569.     
  570.     wInfo = (WinfoH) NewHandleClear(sizeof(WindowInfo));
  571.     if (wInfo == nil) {
  572.         ErrMsg("\pNewHandle(WindowInfo) failed");
  573.         return nil;
  574.     }
  575.     
  576.     (**wInfo).view = Q3View_New();    // Escher View
  577.     if ( (**wInfo).view == nil ) goto fail;
  578.  
  579.     // Set DrawContext, Camera, lightGroup and Renderer
  580.     drawContext = MakeDrawContext(theWindow);
  581.     if ( drawContext == nil ) goto fail;
  582.     status = Q3View_SetDrawContext((**wInfo).view, drawContext);
  583.     if ( status == kQ3Failure ) goto fail;
  584.     status = Q3Object_Dispose(drawContext); 
  585.  
  586.     MakeNewCamera(wInfo, iAspectRatio);
  587.  
  588.     lightGroup = MakeLights();
  589.     if ( lightGroup == nil ) goto fail;
  590.     status = Q3View_SetLightGroup((**wInfo).view, lightGroup);
  591.     if ( status == kQ3Failure ) goto fail;
  592.     // decrease reference count (was increased by Q3View_SetLightGroup
  593.     Q3Object_Dispose(lightGroup);
  594.     
  595.     curLight = 0; // selector for valuecontrol initially undefined
  596.     
  597.     ChooseRenderer((**wInfo).view, iWireFrame);
  598.  
  599.     (**wInfo).shader = Q3LambertIllumination_New() ;
  600.  
  601.     //    Create model to display.
  602.     (**wInfo).model = Q3OrderedDisplayGroup_New();
  603.     if ( (**wInfo).model == nil ) goto fail;
  604.  
  605.     // Set identity transform
  606.     Q3Matrix4x4_SetIdentity(&matrix);
  607.     (**wInfo).rotation = Q3MatrixTransform_New(&matrix);
  608.  
  609.     //    Configure the drawing styles.
  610.     ChooseInterpolation    (wInfo, iNone);        curInterpol     = iNone;
  611.     ChooseBackfacing    (wInfo, iBoth);        curBackfacing     = iBoth;
  612.     ChooseFillStyle        (wInfo, iFilled);    curFillStyle     = iFilled;
  613.  
  614.     return wInfo;
  615.     
  616. fail:
  617.     Dispose3Dinfo(wInfo);
  618.     return nil;
  619. }
  620.  
  621. // ---------------------------------------------------------------------
  622. void    Dispose3Dinfo(WinfoH wInfoH)
  623. {
  624.     TQ3Status    status;
  625.     
  626.     if (wInfoH == nil) return;
  627.     if ((**wInfoH).view != nil)
  628.         status = Q3Object_Dispose((**wInfoH).view);
  629.     if ((**wInfoH).model != nil) {
  630.         // need to dispose properly of everything ...
  631.         status = Q3Object_Dispose((**wInfoH).model);
  632.     }
  633.     if ((**wInfoH).interpolation != nil)
  634.         status = Q3Object_Dispose((**wInfoH).interpolation);
  635.     if ((**wInfoH).backfacing != nil)
  636.         status = Q3Object_Dispose((**wInfoH).backfacing);
  637.     if ((**wInfoH).fillstyle != nil)
  638.         status = Q3Object_Dispose((**wInfoH).fillstyle);
  639.     DisposeHandle((Handle) wInfoH);
  640. }
  641.  
  642.  
  643. // --------------------------------------------------------------------
  644. TQ3DrawContextObject MakeDrawContext(WindowPtr theWindow)
  645. {
  646.     TQ3DrawContextData        drawContextData;
  647.     TQ3MacDrawContextData    macDrawContextData;
  648.     TQ3ColorARGB            ClearColor;
  649.     
  650.     //    Set the background color.
  651.     ClearColor.a = 1.0; /* Solid alpha */
  652.     ClearColor.r = 1.0;
  653.     ClearColor.g = 1.0;
  654.     ClearColor.b = 1.0;
  655.     
  656.     //    Fill in draw context data.
  657.     drawContextData.clearImageMethod = kQ3ClearMethodWithColor;
  658.     drawContextData.clearImageColor = ClearColor;
  659.     drawContextData.pane.min.x = (theWindow->portRect).left;
  660.     drawContextData.pane.max.x = (theWindow->portRect).right;
  661.     drawContextData.pane.min.y = (theWindow->portRect).top;
  662.     drawContextData.pane.max.y = (theWindow->portRect).bottom;
  663.     drawContextData.paneState = kQ3True;
  664.     drawContextData.maskState = kQ3False;
  665.     drawContextData.doubleBufferState = kQ3True;
  666.  
  667.     macDrawContextData.drawContextData = drawContextData;
  668.     macDrawContextData.window = (CWindowPtr) theWindow;
  669.     macDrawContextData.library = kQ3Mac2DLibraryQuickDraw;
  670.     macDrawContextData.viewPort = nil;
  671.     macDrawContextData.grafPort = (CGrafPtr) theWindow;
  672.  
  673.     //    Create draw context.
  674.     return  Q3MacDrawContext_New(&macDrawContextData);
  675.     
  676. }
  677.  
  678. //----------------------------------------------------------------------------------
  679. void    DrawAppSpecificContent(WindowPtr theWindow)
  680. {
  681.     WinfoH wInfo;
  682.     
  683.     wInfo = (WinfoH)GetWRefCon(theWindow);
  684.     if (wInfo == nil)
  685.         return;
  686.     Draw3DPart(wInfo);
  687.     DrawControlPart(wInfo);
  688. }
  689.  
  690. //----------------------------------------------------------------------------------
  691. static void Draw3DPart(WinfoH wInfo)
  692. {
  693.     TQ3Status                status;
  694.     TQ3DrawContextObject        myDrawContext;
  695.     TQ3ViewStatus            myViewStatus;
  696.     WindowInfo                wI = **wInfo;
  697.     
  698.     status = Q3View_StartRendering(wI.view);
  699.     if ( status == kQ3Failure ) goto bail;
  700.     
  701.     if (curInterpol == iPixel)
  702.         SetCursor(*gWatchCursor);
  703.  
  704.     do {
  705.         if (curFillStyle == iFilled) {
  706.             status = Q3Shader_Submit(wI.shader, wI.view);
  707.             if ( status == kQ3Failure ) goto bail;
  708.         }
  709.         status = Q3Style_Submit(wI.interpolation, wI.view);
  710.         if ( status == kQ3Failure ) goto bail;
  711.         status = Q3Style_Submit(wI.backfacing, wI.view);
  712.         if ( status == kQ3Failure ) goto bail;
  713.         status = Q3Style_Submit(wI.fillstyle, wI.view);
  714.         if ( status == kQ3Failure ) goto bail;
  715.         status = Q3Transform_Submit( wI.rotation, wI.view);
  716.         if ( status == kQ3Failure ) goto bail;
  717.         status = Q3DisplayGroup_Submit(wI.model, wI.view);
  718.         if ( status == kQ3Failure ) goto bail;
  719.         myViewStatus = Q3View_EndRendering(wI.view);
  720.     } while ( myViewStatus == kQ3ViewStatusRetraverse );
  721.     
  722.     status = Q3View_GetDrawContext(wI.view, &myDrawContext);
  723.     if ( status == kQ3Failure ) goto bail;
  724.             
  725.     status = Q3Object_Dispose(myDrawContext); 
  726.     // because Q3View_GetDrawContext incremented usage count!
  727.     
  728.     DrawDirections();
  729.     
  730.     InitCursor();
  731.     return;
  732.  
  733. bail:
  734.     SysBeep(50);
  735. }
  736.  
  737. //------------------------------------
  738. static     void    DrawDirections(void)
  739. {
  740.     Point    p;
  741.     short     d = 4; // distance from border
  742.     
  743.     p.h = (g3DViewRect.right - g3DViewRect.left) / 2;
  744.     p.v = g3DViewRect.top + d;
  745.     DrawTriangle(p, up);
  746.     p.v = g3DViewRect.bottom - d;
  747.     DrawTriangle(p, down);
  748.     p.h = g3DViewRect.left + d; 
  749.     p.v = (g3DViewRect.bottom - g3DViewRect.top) / 2;
  750.     DrawTriangle(p, left);
  751.     p.h = g3DViewRect.right - d;
  752.     DrawTriangle(p, right);
  753.     MoveTo(g3DViewRect.right - 20, g3DViewRect.top + 14);
  754.     TextFont(geneva); TextSize(12); TextFace(0);
  755.     DrawString("\p(R)");
  756. }
  757.  
  758. //------------------------------------
  759. static     void    DrawTriangle(Point p, DirectionType e)
  760. {
  761. #define        k   10 
  762.  
  763.     short    x1, y1, x2, y2, x3, y3;
  764.     
  765.     switch (e) {
  766.     case up:    x1 = y1 = x3 = k; y3 = -k; x2 = - k - k; y2 = 0;    break;
  767.     case down:    x1 = y1 = x3 = -k; y3 = k; x2 = k + k; y2 = 0;        break;
  768.     case left:    x1 = y1 = y3 = k; x3 = -k; x2 = 0; y2 = - k - k;    break;
  769.     case right: x1 = y1 = y3 = -k; x3 = k; x2 = 0; y2 = k + k;        break;
  770.     }
  771.         
  772.     MoveTo(p.h, p.v);
  773.     Line(x1, y1); Line(x2, y2); Line(x3, y3);
  774. }
  775.  
  776. //------------------------------------
  777. static    void    DrawControlPart(WinfoH wInfo)
  778. {
  779.     EraseRect(&gContrlRect);
  780.     FrameRect(&gContrlRect);
  781.     if ((**wInfo).vcc != nil)
  782.         DrawVCluster((**wInfo).vcc);
  783. }
  784.  
  785.  
  786. //------------------------------------
  787. static Boolean    ControlClick(Point pt, WindowPtr theWindow)
  788. {
  789.     WinfoH        wInfo;
  790.     OSType        tag;
  791.     TQ3Status    status;
  792.     
  793.     wInfo = (WinfoH)GetWRefCon(theWindow);
  794.     if (wInfo == nil)
  795.         return false;
  796.  
  797.     if ( TakeHit(pt, (**wInfo).vcc) ) {
  798.         tag = GetIdTag((**wInfo).vcc);
  799.         switch (tag) {
  800.             case kQ3GeometryTypeBox:
  801.                     UpdateGeometry(wInfo);
  802.                 break;
  803.                 
  804.             case kQ3CameraTypeOrthographic:
  805.             case kQ3CameraTypeViewPlane:
  806.             case kQ3CameraTypeViewAngleAspect:
  807.                 {
  808.                     TQ3CameraObject    camera;
  809.                 
  810.                     status = Q3View_GetCamera((**wInfo).view, &camera);
  811.                     VCCtoCameraData((**wInfo).vcc, camera);
  812.                     status = Q3View_SetCamera((**wInfo).view, camera);
  813.                     status = Q3Object_Dispose(camera); 
  814.                 }
  815.                 break;
  816.  
  817.             case kQ3LightTypeAmbient:
  818.             case kQ3LightTypeDirectional:
  819.             case kQ3LightTypePoint:
  820.             case kQ3LightTypeSpot:
  821.                 {
  822.                     TQ3CameraObject    camera;
  823.                     TQ3GroupObject    lightGroup;
  824.  
  825.                     status = Q3View_GetLightGroup((**wInfo).view, &lightGroup);
  826.                     VCCtoLight((**wInfo).vcc, lightGroup);                
  827.                 }
  828.                 break;
  829.  
  830.         // add here other types of valueControls
  831.         }
  832.         return true;
  833.     }
  834.     else
  835.         return false;
  836. }
  837.  
  838.  
  839. //----------------------------------------------------------------------------------
  840. static    DirectionType  RotationClick(Point pt, WindowPtr theWindow)
  841. {
  842.     Rect    leftRect, rightRect, upRect, downRect, resetRect;
  843.     Rect    r = g3DViewRect;  // shorthand notation
  844.     short     h3 = (g3DViewRect.right - g3DViewRect.left) / 3;
  845.     short     v3 = (g3DViewRect.bottom - g3DViewRect.top) / 3;
  846.     
  847.     SetRect(&leftRect,     r.left,          r.top + v3,      r.left + h3,   r.bottom - v3);
  848.     SetRect(&rightRect, r.right - h3, r.top + v3,      r.right,         r.bottom - v3);
  849.     SetRect(&upRect,     r.left + h3,  r.top,          r.right - h3,  r.top + v3);
  850.     SetRect(&downRect,     r.left + h3,  r.bottom - v3, r.right - h3,  r.bottom);
  851.     SetRect(&resetRect, r.right - 32,  r.top, r.right,  r.top + 32);
  852.     if (PtInRect(pt, &leftRect))    return left;
  853.     if (PtInRect(pt, &rightRect))     return right;
  854.     if (PtInRect(pt, &upRect))        return up;
  855.     if (PtInRect(pt, &downRect))    return down;
  856.     if (PtInRect(pt, &resetRect))    return reset;
  857.     return none;
  858. }
  859.  
  860. //----------------------------------------------------------------------------------
  861. void    MakeGeometry(WinfoH wInfo, long selector)
  862. {
  863.     if ((**wInfo).model != NULL) {
  864.     // ••• need to release memory allocated in attributes!
  865.         Q3Group_EmptyObjects((**wInfo).model);
  866.         Q3Object_Dispose((**wInfo).model);
  867.     }
  868.     
  869.     switch (selector) {
  870.         case iBox:     (**wInfo).model = MakeBox();
  871.             break;
  872.         case iEllipsoid:// aGeometry = MakeEllipsoid();
  873.                     SysBeep(10);
  874.             break;
  875.         case iCylinder: // aGeometry = MakeCylinder();
  876.                     SysBeep(10);
  877.             break;
  878.         case iCone:     // aGeometry = MakeCone();
  879.                     SysBeep(10);
  880.             break;
  881.         case iTorus:     // aGeometry = MakeTorus();
  882.                     SysBeep(10);
  883.             break;
  884.  
  885.         default:
  886.             break;
  887.     }
  888. }
  889.  
  890.  
  891. //----------------------------------------------------------------------------------
  892. void    MakeDataControl(WinfoH wInfo)
  893. {
  894.     TQ3GroupObject        group;
  895.     TQ3GroupPosition        position;
  896.     TQ3ObjectType        type;
  897.     TQ3Status            status;
  898.     TQ3Object            theObj;
  899.  
  900.     if ((**wInfo).vcc != nil) {
  901.         DisposeVCluster((**wInfo).vcc);
  902.         (**wInfo).vcc = nil;
  903.     }
  904.     
  905.     group = (**wInfo).model;
  906.     type = kQ3ShapeTypeGeometry;
  907.     status = Q3Group_GetFirstPositionOfType(group, type, &position);
  908.     if (status == kQ3Failure)
  909.         return;
  910.         
  911.     status = Q3Group_GetPositionObject ( group, position, &theObj);
  912.     type = Q3Geometry_GetType ( theObj );
  913.     switch (type) {
  914.         case kQ3GeometryTypeBox: 
  915.             (**wInfo).vcc = BoxDataToVCC(theObj);
  916.             break;
  917.             // add here data of other geometries
  918.         default:
  919.             return;
  920.     }
  921. }
  922.  
  923.  
  924. //----------------------------------------------------------------------------------
  925. static void MakeNewCamera (WinfoH wInfo, long selector)
  926. {
  927.     TQ3CameraObject        camera;
  928.     TQ3Status            status;
  929.     
  930.     camera = MakeCamera(selector);
  931.     status = Q3View_SetCamera((**wInfo).view, camera);
  932.     if ( status != kQ3Success )
  933.         ErrMsg("\pSetCamera failed");
  934.     status = Q3Object_Dispose(camera); 
  935.     curCamera = selector;
  936. }
  937.  
  938.  
  939. //----------------------------------------------------------------------------------
  940. static void MakeCameraControl(WinfoH wInfo)
  941. {
  942.     TQ3CameraObject    camera;
  943.     TQ3Status        status;
  944.  
  945.     if ((**wInfo).vcc != nil) {
  946.         DisposeVCluster((**wInfo).vcc);
  947.         (**wInfo).vcc = nil;
  948.     }
  949.     status = Q3View_GetCamera((**wInfo).view, &camera);
  950.     if (status != kQ3Success)
  951.         return;
  952.     (**wInfo).vcc = CameraDataToVCC(camera);
  953.     status = Q3Object_Dispose(camera); 
  954. }
  955.  
  956.  
  957. //----------------------------------------------------------------------------------
  958. static void MakeLightControl (WinfoH wInfo, long selector)
  959. {
  960.     TQ3Status        status;
  961.     TQ3GroupObject    lightGroup;
  962.         
  963.     if ((**wInfo).vcc != nil) {
  964.         DisposeVCluster((**wInfo).vcc);
  965.         (**wInfo).vcc = nil;
  966.     }
  967.     status = Q3View_GetLightGroup((**wInfo).view, &lightGroup);
  968.     (**wInfo).vcc = LightToVCC(lightGroup, selector);
  969. }
  970.  
  971.  
  972. //----------------------------------------------------------------------------------
  973. static void    UpdateGeometry(WinfoH wInfo)
  974. {
  975.     TQ3GroupObject        group;
  976.     TQ3GroupPosition        position;
  977.     TQ3ObjectType        type;
  978.     TQ3Status            status;
  979.     TQ3Object            theObj;
  980.     
  981.     group = (**wInfo).model;
  982.     type = kQ3ShapeTypeGeometry;
  983.     status = Q3Group_GetFirstPositionOfType(group, type, &position);
  984.     if (status == kQ3Failure)
  985.         return;
  986.         
  987.     status = Q3Group_GetPositionObject( group, position, &theObj);
  988.     type = Q3Geometry_GetType( theObj );
  989.     switch (type) {
  990.         case kQ3GeometryTypeBox: {
  991.                 TQ3BoxData    boxData;
  992.                 status = Q3Box_GetData(theObj, &boxData);
  993.                 if (status == kQ3Failure)
  994.                     return; 
  995.                 VCCtoBoxData((**wInfo).vcc, &boxData);
  996.                 status = Q3Box_SetData(theObj, &boxData);
  997.             //    Q3Box_EmptyData(&boxData);
  998.             }
  999.             break;
  1000.             // add here data of other geometries
  1001.         default:
  1002.             return;
  1003.     }
  1004.     status = Q3Group_SetPositionObject( group, position, theObj);
  1005.     status = Q3Object_Dispose(theObj); 
  1006. }
  1007.  
  1008.  
  1009.  
  1010. //----------------------------------------------------------------------------------
  1011. static Boolean GoodFrontWindow(WindowPtr *theWindow, WinfoH *wInfo)
  1012. {
  1013.     WindowPtr    w;
  1014.     Boolean        isGood = true;
  1015.     
  1016.     w = FrontWindow();
  1017.     if (w == nil) // menu item should be disabled!
  1018.         isGood = false;
  1019.     if ( (*(WindowRecord *)w).windowKind != userKind )
  1020.         isGood = false;
  1021.     *theWindow = w;
  1022.     *wInfo = (WinfoH)GetWRefCon(w);
  1023.     if (*wInfo == nil)
  1024.         isGood = false;
  1025.     if (isGood)
  1026.         SetPort(w);
  1027.     return isGood;
  1028. }